home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / os2 / remin301.zip / PATCH301.ZIP / REM2PS.C < prev    next >
C/C++ Source or Header  |  1992-12-28  |  17KB  |  580 lines

  1. /***************************************************************/
  2. /*                                                             */
  3. /*  REM2PS.C                                                   */
  4. /*                                                             */
  5. /*  Print a PostScript calendar.                               */
  6. /*                                                             */
  7. /*  This file is part of REMIND.                               */
  8. /*  Copyright (C) 1992 by David F. Skoll.                      */
  9. /*                                                             */
  10. /***************************************************************/
  11. #include "config.h"
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15. #ifdef HAVE_UNISTD
  16. #include <unistd.h>
  17. #endif
  18. #include "rem2ps.h"
  19. #ifdef HAVE_MALLOC_H
  20. #include <malloc.h>
  21. #endif
  22. #ifdef HAVE_STDLIB_H
  23. #include <stdlib.h>
  24. #endif
  25.  
  26. #ifdef HAVE_PROTOS
  27. #define ARGS(x) x
  28. #else
  29. #define ARGS(x) ()
  30. #endif
  31. #define NEW(type) ((type *) malloc(sizeof(type)))
  32.  
  33. typedef struct _CalEntry {
  34.    struct _CalEntry *next;
  35.    char *entry;
  36. } CalEntry;
  37.  
  38. typedef struct {
  39.    char *name;
  40.    int xsize, ysize;
  41. } PageType;
  42.  
  43. char Days[]="SMTWTFS";
  44.  
  45. PageType Pages[] =
  46. {
  47.    {"Letter", 612, 792},     /* 8.5 x 11 in. */
  48.    {"Tabloid", 792, 1224},   /* 11 x 17 in. */
  49.    {"Ledger", 1224, 792},    /* 17 x 11 in. */
  50.    {"Legal", 612, 1008},     /* 8.5 x 14 in. */
  51.    {"Statement", 396, 612},  /* 5.5 x 8.5 in. */
  52.    {"Executive", 540, 720},  /* 7.5 x 10 in. */
  53.    {"A3", 842, 1190},
  54.    {"A4", 595, 842},
  55.    {"A5", 420, 595},
  56.    {"B4", 729, 1032},
  57.    {"B5", 519, 729},
  58.    {"Folio", 612, 936},
  59.    {"Quarto", 612, 780},
  60.    {"10x14", 720, 1008}
  61. };
  62.  
  63. #define NUMPAGES (sizeof(Pages)/sizeof(Pages[0]))
  64.  
  65. CalEntry *CurEntries;
  66. PageType *CurPage;
  67. char PortraitMode;
  68. char NoSmallCal;
  69.  
  70. char LineBuffer[LINELEN];
  71.  
  72. char *HeadFont="Helvetica";
  73. char *DayFont="Helvetica-BoldOblique";
  74. char *EntryFont="Helvetica";
  75. char *SmallFont="Helvetica";
  76. char *LineWidth = "1";
  77.  
  78. char *HeadSize="14";
  79. char *DaySize="14";
  80. char *EntrySize="8";
  81. char *BorderSize = "6";
  82.  
  83. int validfile = 0;
  84.  
  85. int CurDay;
  86. int MaxDay;
  87. int DayNum;
  88. int WkDayNum;
  89.  
  90. void Init ARGS ((int argc, char *argv[]));
  91. void Usage ARGS ((char *s));
  92. void DoPsCal ARGS ((void));
  93. void DoSmallCal ARGS((char *m, int days, int first, int col));
  94. void WriteProlog ARGS ((void));
  95. void WriteCalEntry ARGS ((void));
  96. void WriteOneEntry ARGS ((char *s));
  97.  
  98. /***************************************************************/
  99. /*                                                             */
  100. /*   MAIN PROGRAM                                              */
  101. /*                                                             */
  102. /***************************************************************/
  103. #ifdef HAVE_PROTOS
  104. PUBLIC int main(int argc, char *argv[])
  105. #else
  106. int main(argc, argv)
  107. int argc;
  108. char argv[];
  109. #endif
  110. {
  111.    /* If stdin is a tty - probably wrong. */
  112.  
  113.    Init(argc, argv);
  114.  
  115.    if (isatty(0)) {
  116.       Usage("Input should not come from a terminal");
  117.    }
  118.  
  119.    /* Search for a valid input file */
  120.    while (!feof(stdin)) {
  121.       gets(LineBuffer);
  122.       if (!strcmp(LineBuffer, PSBEGIN)) {
  123.          if (!validfile) WriteProlog();
  124.          validfile++;
  125.          DoPsCal();
  126.       }
  127.    }
  128.    if (!validfile) {
  129.       fprintf(stderr, "Couldn't find any calendar data!\n");
  130.       exit(1);
  131.    }
  132.    printf("%%%%Trailer\n");
  133.    printf("%%%%Pages: %d\n", validfile);
  134.    return 0;
  135. }
  136.  
  137. /***************************************************************/
  138. /*                                                             */
  139. /*  DoPsCal - emit PostScript for the calendar.                */
  140. /*                                                             */
  141. /***************************************************************/
  142. #ifdef HAVE_PROTOS
  143. void DoPsCal(void)
  144. #else
  145. void DoPsCal()
  146. #endif
  147. {
  148.    char month[40], year[40];
  149.    char prevm[40], nextm[40];
  150.    int days, wkday, prevdays, nextdays;
  151.    int sfirst;
  152.    int i;
  153.    int smallcol;
  154.    CalEntry *c, *d;
  155.  
  156.    printf("%%%%Page: %d %d\n", validfile, validfile);
  157. /* Read the month and year name, followed by # days in month and 1st day of
  158.    month */
  159.    gets(LineBuffer);
  160.    sscanf(LineBuffer, "%s %s %d %d", month, year, &days, &wkday);
  161.    gets(LineBuffer);
  162.    sscanf(LineBuffer, "%s %d", prevm, &prevdays);
  163.    gets(LineBuffer);
  164.    sscanf(LineBuffer, "%s %d", nextm, &nextdays);
  165.    MaxDay = days;
  166.  
  167. /* Emit PostScript to do the heading */
  168.    if (!PortraitMode) printf("XSIZE 0 translate 90 rotate\n");
  169.    printf("(%s %s) doheading\n", month, year);
  170.  
  171. /* Calculate the minimum box size */
  172.    printf("/MinBoxSize ytop MinY sub 7 div def\n");
  173.  
  174. /* If wkday >= 2, then do the small calendars at the top. */
  175.    if (wkday >=2 && !NoSmallCal) {
  176.       smallcol = 0;
  177.       printf("/ysmall ytop def\n");
  178.    }
  179.  
  180. /* Do each entry */
  181.  
  182.    CurEntries = NULL;
  183.    CurDay = 1;
  184.    WkDayNum = wkday;
  185.  
  186.    while(1) {
  187.       gets(LineBuffer);
  188.       if (!strcmp(LineBuffer, PSEND)) break;
  189.  
  190. /* Read the day number - a bit of a hack! */
  191.       DayNum = (LineBuffer[8] - '0') * 10 + LineBuffer[9] - '0';
  192.       if (DayNum != CurDay) {
  193.          for(; CurDay<DayNum; CurDay++) {
  194.         WriteCalEntry();
  195.         WkDayNum = (WkDayNum + 1) % 7;
  196.          }
  197.       }
  198. /* Add the text */
  199.       c = NEW(CalEntry);
  200.       if (!c) {
  201.          fprintf(stderr, "malloc failed - aborting.\n");
  202.      exit(1);
  203.       }
  204.       c->next = NULL;
  205.       c->entry = malloc(strlen(LineBuffer+10) + 1);
  206.       if (!c->entry) {
  207.          fprintf(stderr, "malloc failed - aborting.\n");
  208.      exit(1);
  209.       }
  210.       strcpy(c->entry, LineBuffer+10);
  211.  
  212. /* Put on linked list */
  213.       if (!CurEntries) CurEntries = c;
  214.       else {
  215.          d = CurEntries;
  216.      while(d->next) d = d->next;
  217.      d->next = c;
  218.       }
  219.    }
  220.    for(; CurDay<=days; CurDay++) {
  221.       WriteCalEntry();
  222.       WkDayNum = (WkDayNum + 1) % 7;
  223.    }
  224.  
  225. /* If wkday < 2, set ysmall.  If necessary (only for feb) increase cal size. */
  226.    if (wkday < 2 && !NoSmallCal) {
  227.       smallcol = 5;
  228.       printf("/ysmall ylast def\n");
  229.       if (days == 28 && wkday == 0) {
  230.          printf("/ysmall ymin def /ymin ysmall MinBoxSize sub def\n");
  231.      printf("MinX ymin MaxX ymin L\n");
  232.       }
  233.    }
  234.        
  235.  
  236. /* Now draw the vertical lines */
  237.    for (i=0; i<=7; i++) {
  238.       printf("%d xincr mul MinX add ymin %d xincr mul MinX add topy L\n",
  239.               i, i);
  240.    }
  241.  
  242. /* print the small calendars */
  243.    if (!NoSmallCal) {
  244.       sfirst = wkday - (prevdays % 7);
  245.       if (sfirst < 0) sfirst += 7;
  246.       DoSmallCal(prevm, prevdays, sfirst, smallcol);
  247.       sfirst = wkday + (days % 7);
  248.       if (sfirst >6) sfirst -= 7;
  249.       DoSmallCal(nextm, nextdays, sfirst, smallcol+1);
  250.    }
  251. /* Do it! */
  252.    printf("showpage\n");
  253. }
  254.  
  255. /***************************************************************/
  256. /*                                                             */
  257. /*  WriteProlog - write the PostScript prologue                */
  258. /*                                                             */
  259. /***************************************************************/
  260. #ifdef HAVE_PROTOS
  261. void WriteProlog(void)
  262. #else
  263. void WriteProlog()
  264. #endif
  265. {
  266.    int i;
  267.    int x = CurPage->xsize;
  268.    int y = CurPage->ysize;
  269.  
  270.    if (!PortraitMode) {
  271.       i = x; x = y; y = i;
  272.    }
  273.  
  274. /* Write the document structuring stuff */
  275.    printf("%%!PS-Adobe-\n");
  276.    printf("%%%%DocumentFonts: %s", HeadFont);
  277.    if (strcmp(HeadFont, DayFont)) printf(" %s", DayFont);
  278.    if (strcmp(EntryFont, HeadFont) &&
  279.        strcmp(EntryFont, DayFont)) printf(" %s", EntryFont);
  280.    if (!NoSmallCal && strcmp(SmallFont, HeadFont) &&
  281.        strcmp(SmallFont, DayFont)  &&
  282.        strcmp(SmallFont, EntryFont)) printf(" %s", SmallFont);
  283.    putchar('\n');
  284.    printf("%%%%Creator: Rem2PS\n");
  285.    printf("%%%%Pages: (atend)\n");
  286.    printf("%%%%EndComments\n");
  287.    for (i=0; PSProlog[i]; i++) puts(PSProlog[i]);
  288.    printf("/HeadFont /%s def\n", HeadFont);
  289.    if (!NoSmallCal) printf("/SmallFont /%s def\n", SmallFont);
  290.    printf("/DayFont /%s def\n", DayFont);
  291.    printf("/EntryFont /%s def\n", EntryFont);
  292.    printf("/HeadSize %s def\n", HeadSize);
  293.    printf("/DaySize %s def\n", DaySize);
  294.    printf("/EntrySize %s def\n", EntrySize);
  295.    printf("/XSIZE %d def\n", CurPage->xsize);
  296.    printf("/MinX 36 def\n");
  297.    printf("/MinY 36 def\n");
  298.    printf("/MaxX %d def\n", x-36);
  299.    printf("/MaxY %d def\n", y-36);
  300.    printf("/Border %s def\n", BorderSize);
  301.    printf("%s setlinewidth\n", LineWidth);
  302.  
  303. /* Check if smallfont is fixed pitch */
  304.    if (!NoSmallCal) {
  305.       printf("SmallFont findfont /FontInfo get /isFixedPitch get\n");
  306.  
  307. /* Define SmallString used to set smallfont size */
  308.       printf("{/SmallString (WW ) def}\n");
  309.       printf("{/SmallString (WW) def}\nifelse\n");
  310.    }
  311.    printf("%%%%EndProlog\n");
  312. /* Set the minimum box size */
  313.  
  314. }
  315.  
  316. /***************************************************************/
  317. /*                                                             */
  318. /*  WriteCalEntry - write all entries for one day              */
  319. /*                                                             */
  320. /***************************************************************/
  321. #ifdef HAVE_PROTOS
  322. void WriteCalEntry(void)
  323. #else
  324. void WriteCalEntry()
  325. #endif
  326. {
  327.    CalEntry *c = CurEntries;
  328.    CalEntry *d;
  329.  
  330. /* Move to appropriate location */
  331.    printf("Border ytop %d xincr mul MinX add xincr\n", WkDayNum);
  332.  
  333. /* Set up the text array */
  334.    printf("[\n");
  335.  
  336.    CurEntries = NULL;
  337.  
  338.    while(c) {
  339.       WriteOneEntry(c->entry);
  340.       free(c->entry);
  341.       d = c->next;
  342.       free(c);
  343.       c = d;
  344.    }
  345.    printf("]\n");
  346.  
  347. /* Print the day number */
  348.    printf("(%d)\n", CurDay);
  349. /* Do it! */
  350.    printf("DoCalBox\n");
  351.  
  352. /* Update ymin */
  353.    printf("/y exch def y ymin lt {/ymin y def} if\n");
  354.  
  355. /* If WkDayNum is a Sunday, move to next row. */
  356.    if (WkDayNum == 6 || CurDay == MaxDay) {
  357.       printf("/y ytop MinBoxSize sub def y ymin lt {/ymin y def} if\n");
  358.  
  359. /* Draw the line at the bottom of the row */
  360.       printf("MinX ymin MaxX ymin L\n");
  361.  
  362. /* Update ytop */
  363.       printf("/ylast ytop def\n");
  364.       printf("/ytop ymin def\n");
  365.    }
  366. }
  367.  
  368. /***************************************************************/
  369. /*                                                             */
  370. /*  WriteOneEntry - write an entry for one day                 */
  371. /*                                                             */
  372. /***************************************************************/
  373. #ifdef HAVE_PROTOS
  374. void WriteOneEntry(char *s)
  375. #else
  376. void WriteOneEntry(s)
  377. char *s;
  378. #endif
  379. {
  380.    int c;
  381.    printf("  [");
  382.  
  383. /* Chew up leading spaces */
  384.    while(isspace(*s)) s++;
  385.  
  386.    putchar('(');
  387.    while(*s) {
  388.       c = *s++;
  389.       if (c == '\\' || c == '(' || c == ')') putchar('\\');
  390.       if (!isspace(c)) putchar(c);
  391.       else {
  392.          putchar(')');
  393.          while(isspace(*s)) s++;
  394.      if (!*s) {
  395.             printf("]\n");
  396.         return;
  397.          }
  398.          putchar('(');
  399.       }
  400.    }
  401.    printf(")]\n");
  402. }
  403.  
  404. /***************************************************************/
  405. /*                                                             */
  406. /*  Init - set up parameters                                   */
  407. /*                                                             */
  408. /***************************************************************/
  409. #ifdef HAVE_PROTOS
  410. PUBLIC void Init(int argc, char *argv[])
  411. #else
  412. void Init(argc, argv)
  413. int argc;
  414. char *argv[];
  415. #endif
  416. {
  417.    char *s, *t;
  418.    int i=1;
  419.    int j;
  420.  
  421.    PortraitMode = 1;
  422.    NoSmallCal = 0;
  423.  
  424.    CurPage = Pages;  /* Letter size by default */
  425.  
  426.    while (i < argc) {
  427.       s = argv[i];
  428.       i++;
  429.  
  430.       if (*s++ != '-') Usage("Options must begin with '-'");
  431.  
  432.       switch(*s++) {
  433.          case 's':
  434.         if (i == argc) Usage("Size must be supplied");
  435.         t = argv[i++];
  436.         while(*s) {
  437.            switch(*s++) {
  438.               case 'h': HeadSize = t; break;
  439.           case 'e': EntrySize = t; break;
  440.           case 'd': DaySize = t; break;
  441.                   default: Usage("Size must specify h, e, or d");        
  442.            }
  443.             }
  444.         break;
  445.  
  446.          case 'f':
  447.         if (i == argc) Usage("Font must be supplied");
  448.         t = argv[i++];
  449.         while(*s) {
  450.            switch(*s++) {
  451.               case 'h': HeadFont = t; break;
  452.           case 'e': EntryFont = t; break;
  453.           case 'd': DayFont = t; break;
  454.           case 's': SmallFont = t; break;
  455.                   default: Usage("Font must specify s, h, e, or d");        
  456.            }
  457.             }
  458.         break;
  459.  
  460.          case 'm':
  461.         if (i == argc) Usage("Media must be supplied");
  462.         t = argv[i++];
  463.         CurPage = NULL;
  464.         for (j=0; j<NUMPAGES; j++)
  465.            if (!strcmp(t, Pages[j].name)) {
  466.               CurPage = &Pages[j]; 
  467.           break;
  468.                }
  469.  
  470.         if (!CurPage) {
  471.            fprintf(stderr, "\nUnknown media specified.\n");
  472.                fprintf(stderr, "\nAvailable media types:\n");
  473.                for (j=0; j<NUMPAGES; j++)
  474.               fprintf(stderr, "   %s\n", Pages[j].name);
  475.            exit(1);
  476.             }
  477.         break;
  478.  
  479.          case 'b':
  480.         if (i == argc) Usage("Border must be supplied");
  481.         BorderSize = argv[i++];
  482.         break;
  483.  
  484.          case 't':
  485.         if (i == argc) Usage("Line thickness must be supplied");
  486.         LineWidth = argv[i++];
  487.         break;
  488.  
  489.      case 'l': PortraitMode = 0; break;
  490.  
  491.      case 'c': NoSmallCal = 1; break;
  492.  
  493.      default: Usage("Unrecognized option");
  494.       }
  495.    }
  496. }
  497.  
  498. /***************************************************************/
  499. /*                                                             */
  500. /*  Usage - print usage information                            */
  501. /*                                                             */
  502. /***************************************************************/
  503. #ifdef HAVE_PROTOS
  504. PUBLIC void Usage(char *s)
  505. #else
  506. void Usage(s)
  507. char *s;
  508. #endif
  509. {
  510.    if (s) fprintf(stderr, "\nrem2ps: %s\n\n", s);
  511.  
  512.    fprintf(stderr, "Rem2PS: Produce a PostScript calendar from output of Remind.\n\n");
  513.    fprintf(stderr, "Usage: rem2ps [options]\n\n");
  514.    fprintf(stderr, "Options:\n\n");
  515.    fprintf(stderr, "-l            Do calendar in landscape mode.\n");
  516.    fprintf(stderr, "-c            Do NOT generate small calendars for previous\n");
  517.    fprintf(stderr, "              and next month.\n");
  518.    fprintf(stderr, "-m media      Set page size (eg, Letter, Legal, A4.)  Case sensitive!\n");
  519.    fprintf(stderr, "-f[shed] font Set font for small cal, hdr, cal entries and/or day numbers.\n");
  520.    fprintf(stderr, "-s[hed] size  Set size for header, calendar entries and/or day numbers.\n");
  521.    fprintf(stderr, "-b size       Set border size for calendar entries.\n");
  522.    fprintf(stderr, "-t size       Set line thickness.\n");
  523.    exit(1);
  524. }
  525.  
  526. /***************************************************************/
  527. /*                                                             */
  528. /*  DoSmallCal - do the small calendar for previous or next    */
  529. /*  month.                                                     */
  530. /*                                                             */
  531. /***************************************************************/
  532. #ifdef HAVE_PROTOS
  533. void DoSmallCal(char *m, int days, int first, int col)
  534. #else
  535. void DoSmallCal(m, days, first, col)
  536. char *m;
  537. int days, first, col;
  538. #endif
  539. {
  540.    /* Do the small calendar */
  541.    int i;
  542.    int row = 2;
  543.  
  544.    /* Figure out the font size */
  545.  
  546.    printf("/SmallFontSize MinBoxSize Border sub Border sub 8 div 2 sub def\n");
  547.    printf("SmallFont findfont setfont\n");
  548.    printf("SmallString stringwidth pop /SmallWidth exch def\n");
  549.    printf("SmallWidth 7 mul xincr Border sub Border sub exch div /tmp exch def\n");
  550.    printf("tmp SmallFontSize lt {/SmallFontSize tmp def} if\n");
  551.    printf("SmallFont findfont SmallFontSize scalefont setfont\n");
  552.  
  553.    /* Recalculate SmallWidth */
  554.    printf("SmallString stringwidth pop /SmallWidth exch def\n");
  555.  
  556.    /* Save graphics state */
  557.    printf("gsave\n");
  558.  
  559.    /* Move origin to upper-left hand corner of appropriate box */
  560.    printf("%d xincr mul MinX add ysmall translate\n", col);
  561.  
  562.    /* Print the month */   
  563.    printf("SmallWidth 7 mul (%s) stringwidth pop sub 2 div Border add Border neg SmallFontSize sub moveto (%s) show\n", m, m);
  564.  
  565.    /* Print the days of the week */
  566.    for (i=0; i<7; i++)
  567.       printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize sub 2 sub moveto (%c) show\n", i, Days[i]);
  568.  
  569.    /* Now do the days of the month */
  570.    for (i=1; i<=days; i++) {
  571.       printf("Border %d SmallWidth mul add Border neg SmallFontSize sub SmallFontSize 2 add %d mul sub moveto (%d) show\n", first, row, i);
  572.       first++;
  573.       if (first == 7) { first = 0; row++; }
  574.    }
  575.  
  576.    /* restore graphics state */
  577.    printf("grestore\n");
  578. }
  579.  
  580.